package com.idroc.coelacanth.core.dht;

import com.idroc.coelacanth.core.membership.Endpoint;

/**
 * 一致性hash环节点 工厂
 * @author yuyoo (yuyoo4j@163.com)
 * @date 2009-12-14 下午05:35:38
 */
public final class ConsistendHashNodes {
	
	/**
	 * 简单节点类型
	 */
	public static final int SIMPLE_NODE = 1;
	 
	/**
	 * 节点生成器接口
	 * @author yuyoo (yuyoo4j@163.com)
	 * @date 2009-12-14 下午05:33:26
	 */
	public interface NodeBuilder {
		
		ConsistendHashNode newInstance(int type);
	}
	
	/**
	 * 节点生成器
	 */
	private static NodeBuilder builder = null;
	
	/**
	 * 按照一致性hash节点类型创建实例
	 * @param type -- 节点类型
	 * @return -- 节点
	 */
	public static ConsistendHashNode newNodeInstance(int type) {

		ConsistendHashNode node = null;
		if (null != builder) {
			node = builder.newInstance(type);
		}
		if (null == node && type == SIMPLE_NODE) {
			return new SimpleConsistendHashNode();	
		}		
		return node; 
	} 
	
	/**
	 * 设置节点生成器NodeBuilder
	 * @param b -- 节点生成器
	 */
	public static void setNodeBuilder(NodeBuilder b) {
		
		builder = b;
	}
	

	/**
	 * 一致性Hash环上的简单节点
	 * @author yuyoo (yuyoo4j@163.com)
	 * @date Dec 12, 2009 3:32:23 PM
	 */
	private static class SimpleConsistendHashNode implements ConsistendHashNode {
		
		private int no = -1;
		
		private final int nodeType = SIMPLE_NODE;
		
		private Endpoint endpoint = null;
		
		public int getNo() {
			return no;
		}

		public void setNo(int no) {
			
			if (no < 0) {
				throw new IllegalArgumentException("一致性hash节点编号必须在0<= no <= 2147483647(2^31-1)");
			}
			this.no = no;
		}

		public Endpoint getEndpoint() {
			return endpoint;
		}

		public void setEndpoint(Endpoint endpoint) {
			this.endpoint = endpoint;
		}

		public int getNodeType() { 
			return nodeType;
		}  
		
		@Override
		public String toString() {

			StringBuilder sb = new StringBuilder();
			sb.append("SimpleConsistendHashNode[");
			sb.append("no:").append(no).append(",");
			sb.append("type:").append(nodeType).append(",");
			sb.append("endpoint:").append(endpoint);
			sb.append("]");
			return sb.toString();
		}
	}
}
